using System;
using Microsoft.SPOT;
using System.IO;
using Microsoft.SPOT.IO;
using System.Text;
using System.Threading;

namespace HighAltitude
{
    class SdCardLogger : IDisposable
    {
        static int BUFFER_LEN = 512;
        static byte[] newLineBytes = { 13, 10 };
        byte[] buffer = new byte[BUFFER_LEN * 2];
        int buffPos = 0;

        int asyBuffStart = 0;
        int asyBuffLen = 0;
        //int wrPos = 0;
        bool isActive = true;
        bool newWork = false;
        string filePath;
        int buffOffSet = 0;
        FileStream fileHandle;

        //FileStream fileHandle;
        Thread WriteAsync;

        public SdCardLogger(string FilePath)
        {
            filePath = FilePath;
            fileHandle = new FileStream(FilePath, FileMode.Append);
            WriteAsync = new Thread(writeToSD);
            WriteAsync.Priority = ThreadPriority.Lowest;
            WriteAsync.Start();
            while (!WriteAsync.IsAlive);
            WriteAsync.Suspend();
        }

        public void Write(string Text)
        {
            addToBuffer(Encoding.UTF8.GetBytes(Text));
        }

        public void NewLine()
        {
            addToBuffer(newLineBytes);
        }

        void addToBuffer(byte[] data)
        {
            Array.Copy(data, 0, buffer, buffPos + buffOffSet, data.Length);
            buffPos += data.Length;

            if (buffPos > (BUFFER_LEN * 2 / 3) && !newWork)
            {
                asyBuffStart = buffOffSet;
                asyBuffLen = buffPos; 

                buffPos = 0;
                buffOffSet += BUFFER_LEN;
                if (buffOffSet > BUFFER_LEN) buffOffSet = 0;

                newWork = true;
                WriteAsync.Resume();
            }
        }

        void writeToSD()
        {
            //DateTime startTime;

            while (isActive)
            {
                if (newWork)
                {
                    //startTime = DateTime.Now;
                    //FileStream fileHandle = new FileStream(filePath, FileMode.Append);
                    Thread.Sleep(1);
                    fileHandle.Write(buffer, asyBuffStart, asyBuffLen);
                    Thread.Sleep(1);
                    //fileHandle.Close();
                    fileHandle.Flush();
                    //Debug.Print((DateTime.Now.Subtract(startTime).Ticks / TimeSpan.TicksPerMillisecond).ToString());

                    newWork = false;
                    WriteAsync.Suspend();

                }
            }
        }

        int buffDist(int pos1, int pos2)
        {
            return (pos1 + BUFFER_LEN - pos2) % BUFFER_LEN;
        }

        public void Dispose()
        {
            isActive = false;
            WriteAsync.Resume();
            //fileHandle.Close();
        }
    }
}
